package com.xiguanlezz.cn.common.remote.client.grpc;

import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.UnsafeByteOperations;
import com.xiguanlezz.cn.api.grpc.auto.Metadata;
import com.xiguanlezz.cn.api.grpc.auto.Payload;
import com.xiguanlezz.cn.api.remote.request.Request;
import com.xiguanlezz.cn.api.remote.response.Response;
import com.xiguanlezz.cn.api.utils.NetUtils;
import com.xiguanlezz.cn.common.remote.PayloadRegistry;
import com.xiguanlezz.cn.common.utils.JacksonUtils;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author：习惯了种种
 * @CreateDate：2024/11/19 16:38
 * @Description：GRPC传输对象转换的工具类
 */
public class GrpcUtils {

    /**
     * 将业务层Request对象序列化为GRPC传输层Payload对象
     */
    public static Payload convert(Request request) {
        Metadata metadata = Metadata.newBuilder()
                .setType(request.getClass().getSimpleName())
                .setClientIp(NetUtils.localIP())
                .putAllHeaders(request.getHeaders())
                .build();
        // request转为字节数组
        byte[] jsonBytes = convertRequestToByte(request);
        return Payload.newBuilder()
                .setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
                .setMetadata(metadata)
                .build();
    }

    private static byte[] convertRequestToByte(Request request) {
        Map<String, String> requestHeaders = new HashMap<>(request.getHeaders());
        request.clearHeaders();
        byte[] jsonBytes = JacksonUtils.toJsonBytes(request);
        request.putAllHeader(requestHeaders);
        return jsonBytes;
    }

    public static Payload convert(Response response) {
        byte[] jsonBytes = JacksonUtils.toJsonBytes(response);
        Metadata.Builder metaBuilder = Metadata.newBuilder().setType(response.getClass().getSimpleName());
        return Payload.newBuilder().
                setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))
                .setMetadata(metaBuilder.build()).build();
    }


    /**
     * 将GRPC传输层Payload对象反序列化为业务层Request对象
     */
    public static Object parse(Payload payload) {
        if (Objects.isNull(payload)) {
            return null;
        }
        // 根据metadata上的type决定要反序列化的类型
        Class<?> classType = PayloadRegistry.getClassByType(payload.getMetadata().getType());
        if (classType != null) {
            ByteString byteString = payload.getBody().getValue();
            ByteBuffer byteBuffer = byteString.asReadOnlyByteBuffer();
            Object obj = JacksonUtils.toObj(new ByteBufferBackedInputStream(byteBuffer), classType);
            if (obj instanceof Request) {
                // 如果是request类型，需要将metadata上的header加到obj上
                // 因为在convert时先将header从request中删除了
                ((Request) obj).putAllHeader(payload.getMetadata().getHeadersMap());
            }
            return obj;
        } else {
            throw new RuntimeException("Unknown payload type, payload：" + payload);
        }
    }
}
